import 'dart:async';
import 'dart:developer';

import 'package:dio/dio.dart';
import 'package:edu/constants/app_strings.dart';
import 'package:edu/networks/account/user_api.dart';
import 'package:edu/utils/account_info.dart';
import 'package:edu/utils/data_fetcher.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:rxdart/rxdart.dart';

// 登录方式
enum LoginInputType { accountPassword, phoneVerifyCode, emailVerifyCode }

class LoginPageLogic extends ChangeNotifier {
  LoginInputType type = LoginInputType.accountPassword;

  bool isFetching = false; // 是否正在请求中
  bool obscurePassword = true; // 密码是否显示
  bool isAgreeDeal = false; // 是否同意协议

  // 账号输入框
  late final accountController = TextEditingController();
  late final accountFocusNode = FocusNode();

  // 密码输入框
  late final passwordController = TextEditingController();
  late final passwordFocusNode = FocusNode();

  // 账号输入框流
  late final accountSubject = PublishSubject<String>();
  late final passwordSubject = PublishSubject<String>();

  // 账号输入框订阅
  late final StreamSubscription<String> _accountSubscription;
  late final StreamSubscription<String> _passwordSubscription;

  // 正则表达式
  late final _emailRegex = RegExp(
    r'^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$',
  );
  late final _phoneRegex = RegExp(r'^1[3-9]\d{9}$');

  // 账号输入框是否为邮箱
  bool _isEmailText = false;
  bool _isPhoneText = false;
  bool _isPasswdValid = false;

  late final _cancelToken = CancelToken();

  void init() {
    //对 accountSubject 发射的文本数据进行防抖处理，
    //避免短时间内频繁处理(比如用户快速输入时,只在停止输入1秒后才处理最终输入内容)
    //避免了用户快速输入时频繁触发处理逻辑，减轻不必要的计算或网络请求

    //监听账号输入框
    accountController.addListener(() {
      accountSubject.add(accountController.text);
    });
    passwordController.addListener(() {
      passwordSubject.add(passwordController.text);
    });

    //处理账号输入验证的逻辑
    _accountSubscription = accountSubject.stream
        .sampleTime(const Duration(milliseconds: 1000))
        .listen((text) {
          // 账号输入框是否为邮箱
          if (_emailRegex.hasMatch(text)) {
            _isEmailText = true;
          } else {
            _isEmailText = false;
          }
          // 账号输入框是否为手机号
          if (_phoneRegex.hasMatch(text)) {
            _isPhoneText = true;
          } else {
            _isPhoneText = false;
          }
          notifyListeners();
        });

    //处理密码输入验证的逻辑
    _passwordSubscription = passwordSubject.stream
        .sampleTime(const Duration(milliseconds: 1000))
        .listen((text) {
          // 密码输入框是否合法
          if (text.length >= 8) {
            _isPasswdValid = true;
          } else {
            _isPasswdValid = false;
          }
          notifyListeners();
        });
  }

  @override
  void dispose() {
    accountController.dispose();
    passwordController.dispose();
    accountFocusNode.dispose();
    passwordFocusNode.dispose();
    accountSubject.close();
    passwordSubject.close();
    _accountSubscription.cancel();
    _passwordSubscription.cancel();
    _cancelToken.cancel();
    super.dispose();
  }

  // 登录标题
  String get title {
    switch (type) {
      case LoginInputType.accountPassword:
        return AppStrings.passwordLogin;
      case LoginInputType.phoneVerifyCode:
        return AppStrings.phoneVerifyCodeLogin;
      case LoginInputType.emailVerifyCode:
        return AppStrings.emailVerifyCodeLogin;
    }
  }

  // 登录方式
  String? get subTitle {
    switch (type) {
      case LoginInputType.accountPassword:
        return null;
      case LoginInputType.phoneVerifyCode:
        return AppStrings.phoneVerifyTip;
      case LoginInputType.emailVerifyCode:
        return AppStrings.emailVerifyTip;
    }
  }

  // 键盘类型
  TextInputType get keyboardType {
    switch (type) {
      case LoginInputType.accountPassword:
        return TextInputType.emailAddress;
      case LoginInputType.phoneVerifyCode:
        return TextInputType.phone;
      case LoginInputType.emailVerifyCode:
        return TextInputType.emailAddress;
    }
  }

  // 输入提示
  String get inputHitText {
    switch (type) {
      case LoginInputType.accountPassword:
        return AppStrings.accountHintText;
      case LoginInputType.phoneVerifyCode:
        return AppStrings.phoneHintText;
      case LoginInputType.emailVerifyCode:
        return AppStrings.emailHintText;
    }
  }

  // 登录方式
  String get inputTypeTitle {
    switch (type) {
      case LoginInputType.accountPassword:
        return AppStrings.phoneVerifyCodeLogin;
      case LoginInputType.phoneVerifyCode:
        return AppStrings.emailVerifyCodeLogin;
      case LoginInputType.emailVerifyCode:
        return AppStrings.passwordLogin;
    }
  }

  // 登录按钮是否可用
  bool get mainButtonEnabled {
    if (isFetching) return false;

    switch (type) {
      case LoginInputType.accountPassword:
        return (_isEmailText || _isPhoneText) && _isPasswdValid;
      case LoginInputType.phoneVerifyCode:
        return _isPhoneText;
      case LoginInputType.emailVerifyCode:
        return _isEmailText;
    }
  }

  // 登录按钮文本
  String get mainButtonText {
    switch (type) {
      case LoginInputType.accountPassword:
        return AppStrings.login;
      case LoginInputType.phoneVerifyCode:
        return AppStrings.getCapcha;
      case LoginInputType.emailVerifyCode:
        return AppStrings.getCapcha;
    }
  }

  void clearAccountText() {
    accountController.clear();
  }

  // 切换密码可见
  void switchPasswordVisible() {
    obscurePassword = !obscurePassword;
    notifyListeners();
  }

  // 切换登录方式
  void switchLoginType() {
    if (isFetching) return;

    const types = LoginInputType.values;
    final index = types.indexOf(type);
    final nextIndex = (index + 1) % types.length; // 下一个索引,不能超过3
    type = types[nextIndex];

    // 清空输入框
    accountFocusNode.unfocus();
    passwordFocusNode.unfocus();
    passwordController.clear();
    notifyListeners();
  }

  void resignFucus() {
    accountFocusNode.unfocus();
    passwordFocusNode.unfocus();
  }

  void agreeDealChanged(bool value) {
    isAgreeDeal = value;
    notifyListeners();
  }

  // 登录
  Future<bool> submit() async {
    if (!isAgreeDeal) {
      isAgreeDeal = true;
      notifyListeners();
    }

    if (isFetching) {
      return false;
    }

    switch (type) {
      // 密码登录
      case LoginInputType.accountPassword:
        return _loginWithPassword();
      // 手机验证码登录
      case LoginInputType.phoneVerifyCode:
      //   return _loginWithVerifyCode();
      // 邮箱验证码登录
      case LoginInputType.emailVerifyCode:
        return _loginWithVerifyCode();
    }
  }

  // 验证码登录使用的接口
  Future<bool> _loginWithVerifyCode() async {
    final String type;
    if (_isEmailText) {
      type = 'email';
    } else if (_isPhoneText) {
      type = 'phone_number';
    } else {
      return false;
    }
    try {
      EasyLoading.show(
        indicator: const CircularProgressIndicator(),
        maskType: EasyLoadingMaskType.clear,
        dismissOnTap: false,
      );

      isFetching = true;
      notifyListeners();

      final account = accountController.text;
      final response = await DataFetcher.shared.userApi.verifyCodeForLogin(
        type: type,
        account: account,
        cancelToken: _cancelToken,
      );
      isFetching = false;
      notifyListeners();
      EasyLoading.dismiss();
      if (response.code == 0) {
        final message = type == 'email'
            ? AppStrings.emailVerifyCodeSended
            : AppStrings.phoneNumberVerifyCodeSended;
        EasyLoading.showSuccess(message);
        return true;
      } else {
        EasyLoading.showError(response.message ?? AppStrings.unknownError);
        return false;
      }
    } on DioException catch (e) {
      isFetching = false;
      notifyListeners();
      EasyLoading.dismiss();
      if (e.type == DioExceptionType.cancel) {
        return false;
      }
      EasyLoading.showError(e.toString());
      return false;
    } catch (e) {
      isFetching = false;
      notifyListeners();
      log('Error: $e');
      return false;
    }
  }

  // 密码登录
  Future<bool> _loginWithPassword() async {
    try {
      final UserLoginType type;
      if (_isEmailText) {
        type = UserLoginType.emailPassword;
      } else if (_isPhoneText) {
        type = UserLoginType.phonePassword;
      } else {
        return false;
      }

      EasyLoading.show(
        indicator: const CircularProgressIndicator(),
        maskType: EasyLoadingMaskType.black,
        dismissOnTap: false,
      );
      isFetching = true;
      notifyListeners();

      // 调用后端接口
      final response = await DataFetcher.shared.userApi.login(
        type: UserApi.getLoginType(type),
        account: accountController.text,
        code: passwordController.text,
      );
      isFetching = false;
      notifyListeners();
      EasyLoading.dismiss();

      if (response.code == 0 &&
          response.token != null &&
          response.brief != null) {
        await AccountInfo.shared.login(response.brief!, response.token!);
        return true;
      } else {
        EasyLoading.showError(AppStrings.loginFailed);
        return false;
      }
    } on DioException catch (e) {
      isFetching = false;
      notifyListeners();
      EasyLoading.dismiss();
      if (e.type == DioExceptionType.cancel) {
        return false;
      }
      EasyLoading.showError(e.toString());
      return false;
    } catch (e) {
      isFetching = false;
      notifyListeners();
      log('Error: $e');
      return false;
    }
  }
}
